
<!DOCTYPE html>
<html>
  <head>
    
<meta charset="utf-8" >

<title>个人在ROS工程使用Protobuf的模板和一点心得 | Blog</title>
<meta name="description" content="个人生活，学习记录">

<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/3.7.0/animate.min.css">

<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.7.2/css/all.css" integrity="sha384-fnmOCqbTlWIlj8LyTjo7mOUStjsKC4pOpQbqyi7RrhN7udi9RwhKkMHpvLbHG9Sr" crossorigin="anonymous">
<link rel="shortcut icon" href="https://qiaoxu123.github.io/favicon.ico?v=1589072669553">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.10.0/katex.min.css">
<link rel="stylesheet" href="https://qiaoxu123.github.io/styles/main.css">



<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="https://cdn.bootcss.com/highlight.js/9.12.0/highlight.min.js"></script>



  </head>
  <body>
    <div id="app" class="main">
      <div class="site-header-container">
  <div class="site-header">
    <div class="left">
      <a href="https://qiaoxu123.github.io">
        <img class="avatar" src="https://qiaoxu123.github.io/images/avatar.png?v=1589072669553" alt="" width="32px" height="32px">
      </a>
      <a href="https://qiaoxu123.github.io">
        <h1 class="site-title">Blog</h1>
      </a>
    </div>
    <div class="right">
      <transition name="fade">
        <i class="icon" :class="{ 'icon-close-outline': menuVisible, 'icon-menu-outline': !menuVisible }" @click="menuVisible = !menuVisible"></i>
      </transition>
    </div>
  </div>
</div>

<transition name="fade">
  <div class="menu-container" style="display: none;" v-show="menuVisible">
    <div class="menu-list">
      
        
          <a href="https://qiaoxu123.github.io" class="menu purple-link">
            首页
          </a>
        
      
        
          <a href="https://qiaoxu123.github.io/archives" class="menu purple-link">
            归档
          </a>
        
      
        
          <a href="https://qiaoxu123.github.io/tags" class="menu purple-link">
            标签
          </a>
        
      
    </div>
  </div>
</transition>


      <div class="content-container">
        <div class="post-detail">
          
          <h2 class="post-title">个人在ROS工程使用Protobuf的模板和一点心得</h2>
          <div class="post-info post-detail-info">
            <span><i class="icon-calendar-outline"></i> 2019-10-28</span>
            
              <span>
                <i class="icon-pricetags-outline"></i>
                
                  <a href="https://qiaoxu123.github.io/tag/9b8jYFcLb/">
                    Protobuf
                    
                      ，
                    
                  </a>
                
                  <a href="https://qiaoxu123.github.io/tag/KUvEXNYC1/">
                    个人学习
                    
                      ，
                    
                  </a>
                
                  <a href="https://qiaoxu123.github.io/tag/5HFkONYVv/">
                    ROS
                    
                  </a>
                
              </span>
            
          </div>
          <div class="post-content">
            <p>从上周搞定ROS工程下使用Protbuf的问题后，陆续对原有工程进行了更改，在这一过程中，探索了下Protobuf与ROS工程结合的不同方式，暂时总结了一份模板，并在此记录下心得。</p>
<!-- more -->
<h3 id="1-使用proto的ros节点">1. 使用Proto的ROS节点</h3>
<p>在这贴下个人使用的范例：</p>
<pre><code>.
├── CMakeLists.txt
├── include
│   └── map
│       ├── map.cpp
│       └── map.h
├── package.xml
├── proto
│   └── map.proto
└── src
    └── map_node.cpp
</code></pre>
<p>个人在尝试不同的组织结构的过程中，也试过把proto文件单独设置一个节点，后续节点只需要添加即可，不需要都更改CmakeLists.txt文件。但对比Apollo工程发现，这样做会使工程目录不够清晰，不能直观地看到工程中是否引用了proto文件。再三考虑后还是决定每个节点单独设置proto文件夹来存在proto文件，这样更清晰直观。</p>
<hr>
<h3 id="2-cmakeliststxt模板">2. CmakeLists.txt模板</h3>
<p>目前最终效果如下：</p>
<pre><code class="language-shell">cmake_minimum_required(VERSION 2.8.3)

project(map)

find_package(catkin REQUIRED COMPONENTS
  roscpp
  std_msgs
)

## System dependencies are found with CMake's conventions
list(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake)
include(FindProtobuf)
find_package(Protobuf REQUIRED)

set(proto_dir ${PROJECT_SOURCE_DIR}/proto)
file(GLOB proto_files &quot;${proto_dir}/*.proto&quot;)

# Set up destination directories
catkin_destinations()
set(proto_gen_dir ${CATKIN_DEVEL_PREFIX}/${CATKIN_GLOBAL_INCLUDE_DESTINATION}/${PROJECT_NAME})
set(proto_gen_cpp_dir ${proto_gen_dir})
file(MAKE_DIRECTORY ${proto_gen_dir})
file(MAKE_DIRECTORY ${proto_gen_cpp_dir})
set(protogen_include_dirs ${proto_gen_cpp_dir}/../ ${proto_gen_python_dir})

# Create lists of files to be generated
set(proto_gen_cpp_files &quot;&quot;)
foreach(proto_file ${proto_files})  
  get_filename_component(proto_name ${proto_file} NAME_WE)
  list(APPEND proto_gen_cpp_files 
       ${proto_gen_cpp_dir}/${proto_name}.pb.h 
       ${proto_gen_cpp_dir}/${proto_name}.pb.cc
  )
endforeach(proto_file ${proto_files}) 

# Run protoc and generate language-specific headers.
add_custom_command(
  OUTPUT ${proto_gen_cpp_files}
  COMMAND ${PROTOBUF_PROTOC_EXECUTABLE} --proto_path=${proto_dir} --cpp_out=${proto_gen_cpp_dir} ${proto_files}
  DEPENDS ${PROTOBUF_PROTOC_EXECUTABLE} ${proto_files}
  WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
)

set_source_files_properties(${proto_gen_cpp_files} PROPERTIES GENERATED TRUE)

add_custom_target(${PROJECT_NAME}_generate_headers
  DEPENDS ${proto_gen_cpp_files} 
) 

# Create proto library for lining.
include_directories(${PROTOBUF_INCLUDE_DIR} ${PROTOBUF_INCLUDE_DIR}/../../)
add_library(${PROJECT_NAME}_proto ${proto_gen_cpp_files})
target_link_libraries(${PROJECT_NAME}_proto ${PROTOBUF_LIBRARY})
add_dependencies(${PROJECT_NAME}_proto ${PROJECT_NAME}_generate_headers)

catkin_package(
  INCLUDE_DIRS ${protogen_include_dirs}
  LIBRARIES ${PROJECT_NAME}_proto
)

install(TARGETS ${PROJECT_NAME}_proto
  ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
  LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
  RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
)

install(DIRECTORY ${proto_gen_cpp_dir}/
  DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION}
  FILES_MATCHING PATTERN &quot;*.h&quot;
)

catkin_package(
  INCLUDE_DIRS include 
)

include_directories(
  ${catkin_INCLUDE_DIRS}
  ${PROTOBUF_INCLUDE_DIR}
  ${CATKIN_DEVEL_PREFIX}
  include
)

add_library(${PROJECT_NAME}
  include/${PROJECT_NAME}/map.cpp
)

add_executable(map_node 
  src/map_node.cpp
  include/${PROJECT_NAME}/map.cpp
)

target_link_libraries(${PROJECT_NAME}_node 
  ${catkin_LIBRARIES}
  ${PROTOBUF_LIBRARIES}
  ${Boost_FILESYSTEM_LIBRARY}
  ${Boost_SYSTEM_LIBRARY}
)
</code></pre>
<p>在使用中，有以下几点需要注意：</p>
<ol>
<li>使用时必须保证节点根目录下存在proto文件夹，并放置好proto文件，否则会提示无目标文件错误；</li>
<li>使用时需对应修改下与节点名称相关的变量</li>
<li>注意：生成的proto文件存在于devel目录inlude文件夹下，对应生成节点名称的文件夹，下面存在生成的变量。</li>
<li><code>include_directories</code>目录中包含<code>${CATKIN_DEVEL_PREFIX}</code>宏，之后才可以引用devel文件目录中的proto生成文件；</li>
</ol>

          </div>
        </div>

        
          <div class="next-post">
            <a class="purple-link" href="https://qiaoxu123.github.io/post/ubuntu18-protobuf-memory-share-note/">
              <h3 class="post-title">
                下一篇：Ubuntu18下ROS使用Protobuf共享内存实现节点通信
              </h3>
            </a>
          </div>
          
      </div>

      

      <div class="site-footer">
  <div class="slogan">个人生活，学习记录</div>
  <div class="social-container">
    
      
    
      
    
      
    
      
    
      
    
  </div>
  Powered by <a href="https://github.com/getgridea/gridea" target="_blank">Gridea</a> | <a class="rss" href="https://qiaoxu123.github.io/atom.xml" target="_blank">RSS</a>
</div>


    </div>
    <script type="application/javascript">

hljs.initHighlightingOnLoad()

var app = new Vue({
  el: '#app',
  data: {
    menuVisible: false,
  },
})

</script>




  </body>
</html>
